package com.button.boot.active.config;

import javax.jms.ConnectionFactory;
import javax.jms.Queue;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.ActiveMQSession;
import org.apache.activemq.RedeliveryPolicy;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;

@Configuration
@EnableJms
public class ActiveMqConfig {
    @Bean
    public JmsListenerContainerFactory<?> queueListenerFactory(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setPubSubDomain(false);
        factory.setConnectionFactory(connectionFactory);
        return factory;
    }

    @Bean //此处是结合springboot设置的redeliveryPolicy
    public RedeliveryPolicy redeliveryPolicy(){
        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
        //设置初始化重发延迟时间，默认1000毫秒
        redeliveryPolicy.setInitialRedeliveryDelay(1000);
        //设置最大重发次数，默认为6
        redeliveryPolicy.setMaximumRedeliveries(1);
        //是否开启重发延迟大小倍数递增，默认false
        redeliveryPolicy.setUseExponentialBackOff(true);
        //重发延迟递增倍数，默认为5
        redeliveryPolicy.setBackOffMultiplier(2);
        //这个参数主要是为了防止高并发下，消息重发会在同一时刻发生，让消息在时间上消费的更加均衡，默认为false
        redeliveryPolicy.setUseCollisionAvoidance(true);
        //设置下次重发延迟波动百分比，默认0.15，此处写成15是因为源码中对参数*0.01
        redeliveryPolicy.setCollisionAvoidancePercent((short)15);
        //设置最大重发延迟，默认为-1，表示无限增大
        redeliveryPolicy.setMaximumRedeliveryDelay(10000);
        return redeliveryPolicy;
    }
    @Bean
    public ActiveMQConnectionFactory activeMQConnectionFactory(@Autowired RedeliveryPolicy redeliveryPolicy, @Value("${spring.activemq.broker-url}") String url){
        ActiveMQConnectionFactory activeMQConnectionFactory=new ActiveMQConnectionFactory(url);
        activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
        return activeMQConnectionFactory;
    }
    
    @Bean
    public JmsListenerContainerFactory<?> queueListenerACKFactory(@Autowired ActiveMQConnectionFactory activeMQConnectionFactory) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setPubSubDomain(false);
        activeMQConnectionFactory.setTrustAllPackages(true);
        factory.setConnectionFactory(activeMQConnectionFactory);
        /**
         * ack设置为activemq独有的单条确认模式：4,
         * 至于为什么不设置为客户端手动确认：2,因为客户端手动确认会失效,
         * 原因为spring框架会判断是否是2，如果是2会spring框架会帮你确认,
         * 可查看AbstractMessageListenerContainer[commitIfNecessary()]
         */
        factory.setSessionAcknowledgeMode(ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);
        return factory;
    }

    @Bean
    public JmsListenerContainerFactory<?> topicListenerFactory(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setPubSubDomain(true);
        factory.setConcurrency("1");
        factory.setConnectionFactory(connectionFactory);
        return factory;
    }

    @Bean
    public Queue queueString(){
        return new ActiveMQQueue("queue_string");
    }

    @Bean
    public Queue queueUser(){
        return new ActiveMQQueue("queue_user");
    }

    @Bean
    public Queue queueReturn(){
        return new ActiveMQQueue("queue_return");
    }

    @Bean
    public Queue queueStringACK(){
        return new ActiveMQQueue("queue_ack");
    }

    @Bean
    public Topic topicString(){
        return new ActiveMQTopic("topic_string");
    }

    @Bean
    public Topic topicUser(){
        return new ActiveMQTopic("topic_user");
    }

    @Bean
    public Topic delayTopicString(){
        return new ActiveMQTopic("topic_delay");
    }
}
